'use client';

import './style.scss';
import Link from 'next/link';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useState, useEffect, useCallback, useMemo, MouseEvent } from 'react';
import useErrorAlert from '@/hooks/useErrorAlert';
import { Menu } from 'lucide-react';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBookmark as nBookmark, faThumbsUp as nThumbsUp, faThumbsDown as nThumbsDown, faFlag as nFlag, faPenToSquare, faTrashCan } from '@fortawesome/free-regular-svg-icons';
import { faQrcode, faPrint, faLink, faShareNodes, faBookmark as yBookmark, faThumbsUp as yThumbsUp, faThumbsDown as yThumbsDown, faFlag as yFlag } from '@fortawesome/free-solid-svg-icons';
import Loading from '@/app/component/Loading';
import Comment from '@/app/(main)/(forum)/comment/view';
import LatestList from '@/app/(main)/(forum)/post/_component/LatestPosts';
import { BoardResponse } from '@/types/response/forum/board';
import { PostResponse } from '@/types/response/forum/post';
import Content from '../_component/Content';
import QRCode from '../_component/QRCode';
import Copied from '../_component/Copied';
import SnsShare from '../_component/SnsShare';
import Report from '../_component/Report';
import { Reaction } from '@/constants/forum';
import { fetchApi, getDateTime, throwError, formatDate, isDateOverdue } from '@/lib/utils/client';
import { isBoardAdmin } from '@/lib/utils/permission';
import useAuth from '@/hooks/useAuth';

type Props = {
	_board: BoardResponse,
	_post: PostResponse
};

export default function View({ _board, _post }: Props)
{
	const router = useRouter();
	const { member, loginCheck } = useAuth();

	// 신고 횟수 초과 게시글은 접근 불가 (첫 진입 시 1회만 검사)
	useEffect(() => {
		if (_post.reports > _board.boardMeta.view.blameHideCount && _board.boardMeta.view.blameHideCount > 0) {
			alert('비공개 게시글입니다.');
			router.replace(`/board/${_post.boardCode}${window.location.search}`);
		}
	}, [_post.reports, _post.boardCode, _board.boardMeta.view.blameHideCount, router]);

	const { setError } = useErrorAlert();
	const [loading, setLoading] = useState<boolean>(false);
	const [qrCode, setQrCode] = useState<boolean>(false);
	const [copied, setCopied] = useState<boolean>(false);
	const [snsShare, setSnsShare] = useState<boolean>(false);
	const [report, setReport] = useState<boolean>(false);
	const [hasLike, setHasLike] = useState<boolean>(_post.hasLike);
	const [hasDisLike, setHasDisLike] = useState<boolean>(_post.hasDislike);
	const [hasBookmark, setHasBookmark] = useState<boolean>(_post.hasBookmark);
	const [hasReport, setHasReport] = useState<boolean>(_post.hasReport);
	const isOwner = member?.id === _post.memberID;
	const canManage = isOwner || isBoardAdmin(_board.boardManager, member);
	const writerThumb = useMemo(() => _post.writer?.thumb ?? '/resources/thumb.gif', [_post.writer?.thumb]);
	const writerIcon = useMemo(() => _post.writer?.icon ?? _post.writer?.gradeImage ?? null, [_post.writer?.icon, _post.writer?.gradeImage]);
	const writerName = useMemo(() => _post.writer?.name ?? _post.name ?? '-', [_post.writer?.name, _post.name]);
	const hasFunction = _board.boardMeta.view.allowLike
		|| _board.boardMeta.view.allowDislike
		|| _board.boardMeta.view.allowBookmark
		|| _board.boardMeta.view.allowBlame
		|| canManage;

	const toggleQRCode = useCallback((e: MouseEvent<HTMLAnchorElement>) => {
		e.preventDefault();
		setQrCode((prev) => !prev);
	}, []);

	const handlePrint = useCallback(() => {
		window.print();
	}, []);

	const toggleCopied = useCallback((e: MouseEvent<HTMLAnchorElement>) => {
		e.preventDefault();
		setCopied((prev) => !prev);
	}, []);

	const toggleSnsShare = useCallback((e: MouseEvent<HTMLAnchorElement>) => {
		e.preventDefault();
		setSnsShare((prev) => !prev);
	}, []);

	// 좋아요/싫어요
	const handleReaction = useCallback(async (e: MouseEvent<HTMLButtonElement>) => {
		const reaction = Number(e.currentTarget.value);

		if (!loginCheck()) {
			return;
		}

		setLoading(true);

		try {
			const res = await fetchApi('/api/forum/posts/' + _post.id + '/reaction', { method: 'POST', body: { reaction } });
			if (res.success) {
				switch (reaction) {
					case Reaction.Like:
						setHasLike(prev => !prev);
						setHasDisLike(false);
						break;
					case Reaction.Dislike:
						setHasDisLike(prev => !prev);
						setHasLike(false);
						break;
				}
			} else {
				throwError(res);
			}
		} catch (err) {
			if (err instanceof Error) setError(err.message);
		} finally {
			setLoading(false);
		}
	}, [_post.id, loginCheck, setError]);

	// 즐겨찾기
	const handleBookmark = useCallback(async () => {
		if (!loginCheck()) {
			return;
		}

		setLoading(true);
		try {
			const res = await fetchApi('/api/forum/posts/' + _post.id + '/bookmark', { method: 'POST' });
			if (res.success) {
				setHasBookmark(prev => !prev);
			} else {
				throwError(res);
			}
		} catch (err) {
			if (err instanceof Error) setError(err.message);
		} finally {
			setLoading(false);
		}
	}, [_post.id, loginCheck, setError]);

	// 신고하기 시작
	const handleReport = useCallback(() => {
		if (hasReport) {
			alert('이미 신고하셨습니다.');
			return;
		}

		if (!loginCheck()) {
			return;
		}

		setReport((prev) => !prev);
	}, [loginCheck, hasReport]);

	// 수정하기
	const handleEdit = useCallback(() => {
		if (!loginCheck()) {
			return;
		}

		// 게시글 삭제 보호 확인
		if (_board.boardMeta.general.allowUpdateProtection && !isBoardAdmin(_board.boardManager, member)) {
			if (isDateOverdue(_post.createdAt, _board.boardMeta.general.updateProtectionDays)) {
				return alert(`게시글 작성 후 ${_board.boardMeta.general.updateProtectionDays}일이 지나 수정이 불가능합니다.`);
			}
		}

		router.push(`/post/edit/${_post.id}`);
	}, [loginCheck, member, _board, _post, router]);

	// 게시글 삭제
	const handleDelete = useCallback(() => {
		if (!loginCheck()) {
			return;
		}

		// 게시글 삭제 보호 확인
		if (_board.boardMeta.general.allowDeleteProtection && !isBoardAdmin(_board.boardManager, member)) {
			if (isDateOverdue(_post.createdAt, _board.boardMeta.general.deleteProtectionDays)) {
				return alert(`게시글 작성 후 ${_board.boardMeta.general.deleteProtectionDays}일이 지나 삭제가 불가능합니다.`);
			}
		}

		if (confirm('정말 삭제하시겠습니까?')) {
			setLoading(true);
			fetchApi('/api/forum/posts/' + _post.id, { method: 'DELETE' }).then(res => {
				if (res.success) {
					alert('게시글이 삭제되었습니다.');
					router.push(`/board/${_post.boardCode}`);
				} else {
					throwError(res);
				}
			}).catch((err) => {
				setError(err.message);
			}).finally(() => {
				setLoading(false);
			});
		}
	}, [loginCheck, member, _board, _post, router, setError]);

	return (
		<div id='postView'>
			{loading && <Loading />}

			<QRCode isEnable={true} open={qrCode} onChange={setQrCode} />
			<Copied isEnable={true} open={copied} onChange={setCopied} />
			<SnsShare isEnable={true} open={snsShare} onChange={setSnsShare} />
			<Report isEnable={true} open={report} onChange={setReport} onComplete={setHasReport} postID={_post.id} memberID={member?.id} />

			{/* 글 제목 */}
			<section className='subject whitespace-normal break-words'>
				{_post.boardPrefixID && ("[" + _post.boardPrefix.name + "]")} {_post.subject}
			</section>

			<hr />

			{/* 글 작성자/작성일시/부가기능들 */}
			<section className='attribution'>
				{_board.boardMeta.view.showMemberThumb && (
				<div>
					<article className='writer-thumb'>
						<Image src={writerThumb} alt='회원 사진' width={84} height={0} />
					</article>
				</div>
				)}
				<div>
					<article className='writer-info'>
						<ul>
							{_post.writer ? (
								<>
									<li>
										{_board.boardMeta.view.showMemberIcon && writerIcon && (
											<Image src={writerIcon} alt="" width={16} height={16} className="inline-block mr-1 align-middle" />
										)}
										<span>{writerName}</span>
									</li>
									{_board.boardMeta.view.showMemberRegDate && (
										<li>{formatDate(_post.writer.createdAt)} 가입</li>
									)}
									{_board.boardMeta.view.showMemberSummary && (
										<li>{_post.writer.summary}</li>
									)}
								</>
							) : (
								<li>{_post.name ?? '-'}</li>
							)}
						</ul>
					</article>

					<article className='post-info'>
						<ul>
							<li>조회 {_post.views}</li>
							<li>댓글 {_post.comments}</li>
							{_board.boardMeta.view.allowLike && (
								<li>좋아요 {_post.likes}</li>
							)}
							{_board.boardMeta.view.allowDislike && (
								<li>싫어요 {_post.dislikes}</li>
							)}
							<li>IP {_post.ipAddress}</li>
						</ul>
					</article>

					<article className='post-date'>
						작성일시 {getDateTime(_post.createdAt)}
					</article>

					<article className='functions'>
						<ul>
							{_board.boardMeta.view.allowPostUrlQrCode && (
							<li>
								<a href='#' rel='noreferrer' onClick={toggleQRCode}><FontAwesomeIcon icon={faQrcode} /> QR</a>
							</li>
							)}
							{_board.boardMeta.view.allowPrint && (
							<li>
								<a href='#' rel='noreferrer' onClick={handlePrint}><FontAwesomeIcon icon={faPrint} /> 인쇄</a>
							</li>
							)}
							{_board.boardMeta.view.allowPostUrlCopy && (
							<li>
								<a href='#' rel='noreferrer' onClick={toggleCopied}><FontAwesomeIcon icon={faLink} /> 주소</a>
							</li>
							)}
							{_board.boardMeta.view.allowSnsShare && (
							<li>
								<a href='#' rel='noreferrer' onClick={toggleSnsShare}><FontAwesomeIcon icon={faShareNodes} /> 공유</a>
							</li>
							)}
						</ul>
					</article>
				</div>
			</section>

			<hr />

			{/* 글 내용 */}
			<section className='content'>
				<Content boardMeta={_board.boardMeta} content={_post.content} boardManagers={_board.boardManager}></Content>

				{_post.tagList.length > 0 && (
					<article>
						{/* 태그 표시 */}
						{_post.tagList.map((row, i) => (
							<span key={i}>
								<Link href={`/tag/${row.slug}`}>#{row.slug}</Link>
							</span>
						))}
					</article>
				)}
			</section>

			<hr />

			{/* 제어 버튼들 */}
			<section className='controls'>
				<article>
					<Link href={`/board/${_post.boardCode}${window.location.search}`} className='btn btn-default'>목록</Link>

					{hasFunction && _board.boardMeta.view.allowPrevNextBotton && (
						<>
						{!!_post.prevID && (
							<Link href={`/post/${_post.prevID}`} className='btn btn-default'>이전</Link>
						)}
						{!!_post.nextID && (
							<Link href={`/post/${_post.nextID}`} className='btn btn-default'>다음</Link>
						)}
						</>
					)}
				</article>

				{hasFunction ? (
				<article className='functions'>
					{_board.boardMeta.view.allowLike && (
					<div className='hidden sm:block'>
						<button type='button' className='btn btn-default' title='좋아요' value={Reaction.Like} onClick={handleReaction}>
							<FontAwesomeIcon icon={!hasLike ? nThumbsUp : yThumbsUp } />
						</button>
					</div>
					)}
					{_board.boardMeta.view.allowDislike && (
					<div className='hidden sm:block'>
						<button type='button' className='btn btn-default' title='싫어요' value={Reaction.Dislike} onClick={handleReaction}>
							<FontAwesomeIcon icon={!hasDisLike ? nThumbsDown : yThumbsDown } />
						</button>
					</div>
					)}
					{_board.boardMeta.view.allowBookmark && (
					<div className='hidden md:block'>
						<button type='button' className='btn btn-default' onClick={handleBookmark}>
							<FontAwesomeIcon icon={!hasBookmark ? nBookmark : yBookmark } /> 즐겨찾기
						</button>
					</div>
					)}
					{_board.boardMeta.view.allowBlame && (
					<div className='hidden xlm:block'>
						<button type='button' className='btn btn-default' onClick={handleReport}>
							<FontAwesomeIcon icon={!hasReport ? nFlag : yFlag } /> 신고
						</button>
					</div>
					)}
					{canManage && (
						<>
						<div className='hidden xl:block'>
							<button type='button' className='btn btn-default' onClick={handleEdit}>수정</button>
						</div>
						<div className='hidden xl:block'>
							<button type='button' className='btn btn-default' onClick={handleDelete}>삭제</button>
						</div>
						</>
					)}
					<div className='block xl:hidden'>
						<DropdownMenu>
						<DropdownMenuTrigger asChild>
							<button type='button' className='btn btn-default' title='더보기'>
								<Menu className='w-5 h-5' />
							</button>
						</DropdownMenuTrigger>
						<DropdownMenuContent align='end'>
							{_board.boardMeta.view.allowLike && (
							<DropdownMenuItem className='block sm:hidden'>
								<button type="button" value={Reaction.Like} onClick={handleReaction}><FontAwesomeIcon icon={!hasLike ? nThumbsUp : yThumbsUp } /> 좋아요</button>
							</DropdownMenuItem>
							)}
							{_board.boardMeta.view.allowDislike && (
							<DropdownMenuItem className='block sm:hidden'>
								<button type="button" value={Reaction.Dislike} onClick={handleReaction}><FontAwesomeIcon icon={!hasDisLike ? nThumbsDown : yThumbsDown } /> 싫어요</button>
							</DropdownMenuItem>
							)}
							{_board.boardMeta.view.allowBookmark && (
							<DropdownMenuItem className='block md:hidden' onClick={handleBookmark}><FontAwesomeIcon icon={!hasBookmark ? nBookmark : yBookmark } /> 즐겨찾기</DropdownMenuItem>
							)}
							{_board.boardMeta.view.allowBlame && (
							<DropdownMenuItem className='block xlm:hidden' onClick={handleReport}><FontAwesomeIcon icon={!hasReport ? nFlag : yFlag } /> 신고</DropdownMenuItem>
							)}
							{canManage && (
								<>
								<DropdownMenuItem className='block xl:hidden' onClick={handleEdit}><FontAwesomeIcon icon={faPenToSquare} /> 수정</DropdownMenuItem>
								<DropdownMenuItem className='block xl:hidden' onClick={handleDelete}><FontAwesomeIcon icon={faTrashCan} /> 삭제</DropdownMenuItem>
								</>
							)}
						</DropdownMenuContent>
						</DropdownMenu>
					</div>
				</article>

				) : (

				_board.boardMeta.view.allowPrevNextBotton && (
				<article>
					{!!_post.prevID && (
						<Link href={`/post/${_post.prevID}`} className='btn btn-default'>이전</Link>
					)}
					{!!_post.nextID && (
						<Link href={`/post/${_post.nextID}`} className='btn btn-default'>다음</Link>
					)}
				</article>

				)
				)}
			</section>

			<br/>

			{/* 댓글 */}
			<Comment _board={_board} _post={_post} />

			{/* 게시판 최근 글 */}
			<LatestList boardListMeta={_board.boardMeta.list} boardID={_board.id} boardCode={_board.code} postID={_post.id} />
		</div>
	);
}